<template>
  <common-dialog
    :show="dialogConfig.show"
    :title="dialogConfig.title"
    :buttons="dialogConfig.buttons"
    width="1000px"
    :show-cancel="false"
    @close="dialogConfig.show = false"
  >
    <div class="cut-image-panel">
      <VueCropper
        ref="vueCropperRef"
        class="cropper"
        :img="sourceImage"
        outputType="png"
        :autoCrop="true"
        :autoCropWidth="cutWidth"
        :autoCropHeight="Math.round(cutWidth * scale)"
        :fixed="true"
        :fixedNumber="[1, scale]"
        :centerBox="true"
        :full="false"
        @realTime="prview"
        mode="100%"
      ></VueCropper>
      <div class="preview-panel">
        <div class="preview-image">
          <img :src="previewsImage" alt="" />
        </div>
        <el-upload
          :multiple="false"
          :show-file-list="false"
          :http-request="selectFile"
          :accept="imageAccept"
        >
          <el-button type="primary" class="select-btn">选择图片</el-button>
        </el-upload>
      </div>
    </div>
    <div class="info">建议上传至少 {{ cutWidth }} * {{ Math.round(cutWidth * scale) }}的图片</div>
  </common-dialog>
</template>

<script setup lang="ts">
import 'vue-cropper/dist/index.css'
import { VueCropper } from 'vue-cropper'
import { inject, nextTick, ref, withDefaults } from 'vue'
import type { UploadRawFile, UploadRequestOptions } from 'element-plus'
import message from '@/utils/message'

/**
 * 参数解释
 *
 * img  裁剪图片的地址 url地址，base64，blob
 * outputSize:1 裁剪生成图片的质量
 * outputType:'jpeg'    裁剪生成图片的格式jpeg,png，webp
 * info:true   裁剪框的大小信息
 * canScale:false   图片是否允许滚轮缩放
 * autoCrop:true    是否默认生成截图框
 * autoCropwidth:150    默认生成截图框宽度
 * autoCropHeight:150   默认生成截图框高度
 * fixedBox:false   固定截图框大小不允許改变
 * fixed:false  是否开启截图框宽高固定比例，这个如果设置为true，截图框会是固定比例缩放的，如果设置为false，则截图框的狂宽高比例就不固定了
 * fixedNumber:[1，1]   截图框的宽高比例［宽度，高度］
 * canMove：true    上传图片是否可以移动
 * canMoveBox:true  截图框能否拖动
 * original:false   上传图片按照原始比例渲染
 * centerBox:true   截图框是否被限制在图片里面
 * infoTrue:true    true为展示真实输出图片宽高  false展示看到的截图框宽高
 * full:true    是否输出原图比例的截图
 * enlarge:'1'  图片根据截图框输出比例倍数
 * mode:'contain'   图片默认渲染方式contain，cover，100px，100% auto
 */

const props = withDefaults(
  defineProps<{
    cutWidth: number
    scale: number
  }>(),
  {
    cutWidth: 400,
    scale: 0.5
  }
)

const dialogConfig = ref({
  show: false,
  title: '上传图片',
  buttons: [
    {
      type: 'primary' as const,
      text: '确定',
      click: (e: any): void => {
        cutImage()
      }
    }
  ]
})

//上传文件能接受的后缀
const imageAccept = ref('.jpg,.png,.gif,.bmp,.webp')
const vueCropperRef = ref()
const previewsImage = ref()
const sourceImage = ref()
const prview = (data: any) => {
  vueCropperRef.value.getCropData((data: any) => {
    previewsImage.value = data
  })
}

const selectFile = (file: UploadRequestOptions) => {
  const rawFile = file.file
  let img = new FileReader()
  img.readAsDataURL(rawFile)
  img.onload = ({ target }) => {
    sourceImage.value = target?.result
  }
  return Promise.resolve()
}

const show = () => {
  dialogConfig.value.show = true
  sourceImage.value = ''
  nextTick(() => {
    previewsImage.value = ''
  })
}

defineExpose({
  show
})

const cutImageCallback = inject('cutImageCallback') as any

//点击确定开始切图的方法
const cutImage = () => {
  const cropW = Math.round(vueCropperRef.value.cropW)
  const cropH = Math.round(vueCropperRef.value.cropH)
  console.log(cropW, cropH, '剪切的高宽')

  if (cropH == 0 || cropW == 0) {
    message.warning('请选择图片')
    return
  }

  if (cropW < props.cutWidth || cropH < Math.round(props.cutWidth * props.scale)) {
    message.warning(`图片尺存至少满足(${props.cutWidth}*${props.cutWidth * props.scale})`)
    return
  }
  //返回切割后的图片
  vueCropperRef.value.getCropBlob((blob: Blob) => {
    //生成一个临时文件
    const file = new File([blob], 'temp.' + blob.type.substring(blob.type.indexOf('/') + 1), {
      type: blob.type
    })
    dialogConfig.value.show = false
    //向父级组件回调
    cutImageCallback({
      coverImage: file
    })
  })
}
</script>

<style lang="less" scoped>
.cut-image-panel {
  display: flex;
  .cropper {
    flex: 1;
    height: 500px;
  }
  .preview-panel {
    width: 200px;
    margin-left: 20px;
    text-align: center;
    .preview-image {
      width: 100%;
      height: 200px;
      background: #f6f6f6;
      display: flex;
      align-items: center;
    }
    img {
      width: 100%;
    }
  }
  .select-btn {
    margin-top: 20px;
  }
}
.info {
  color: #6b6b6b;
}
</style>
